package handler

import (
	"context"
	"errors"

	"go.uber.org/zap"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/emptypb"
	"gorm.io/gorm"

	"mxshop_srvs/goods_srv/model"
	proto "mxshop_srvs/goods_srv/proto/gen/v1"
)

func (s *Service) BrandList(_ context.Context, req *proto.BrandFilterRequest) (*proto.BrandListResponse, error) {
	count, err := s.DB.GetBrandsCount()
	if err != nil {
		return nil, status.Error(codes.Internal, "")
	}

	brands, err := s.DB.GetBrandList(int(req.Pages), int(req.PagePerNums))
	if err != nil {
		return nil, status.Error(codes.Internal, "")
	}

	var data []*proto.BrandInfoResponse
	for _, brand := range brands {
		data = append(data, &proto.BrandInfoResponse{
			Id:   brand.ID,
			Name: brand.Name,
			Logo: brand.Logo,
		})
	}

	return &proto.BrandListResponse{
		Total: int32(count),
		Data:  data,
	}, nil
}

func (s *Service) CreateBrand(_ context.Context, req *proto.BrandRequest) (*proto.BrandInfoResponse, error) {
	if req.Name == "" {
		return nil, status.Error(codes.InvalidArgument, "")
	}

	ok, err := s.DB.BrandExistsByName(req.Name)
	if err != nil {
		zap.L().Error("judge brand is exists failed", zap.Error(err))
		return nil, status.Error(codes.Internal, "")
	}
	if ok {
		return nil, status.Error(codes.AlreadyExists, "")
	}

	var brand = model.Brands{
		Name: req.Name,
		Logo: req.Logo,
	}
	brandID, err := s.DB.CreateBrand(&brand)
	if err != nil {
		zap.L().Error("creates a brand failed", zap.Error(err))
		return nil, status.Error(codes.Internal, "")
	}
	return &proto.BrandInfoResponse{
		Id:   brandID,
		Name: req.Name,
		Logo: req.Logo,
	}, nil
}

func (s *Service) DeleteBrand(_ context.Context, req *proto.BrandRequest) (*emptypb.Empty, error) {
	row, err := s.DB.DeleteBrand(req.Id)
	if err != nil {
		return nil, status.Error(codes.Internal, "")
	}
	if row == 0 {
		return nil, status.Error(codes.NotFound, "")
	}

	return &emptypb.Empty{}, nil
}

func (s *Service) UpdateBrand(_ context.Context, req *proto.BrandRequest) (*emptypb.Empty, error) {
	if req.Id == 0 {
		return nil, status.Error(codes.InvalidArgument, "")
	}

	brand, err := s.DB.GetBrandByID(req.Id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, status.Error(codes.NotFound, "")
		}
		return nil, status.Error(codes.Internal, "")
	}

	if req.Name != "" {
		brand.Name = req.Name
	}
	if req.Logo != "" {
		brand.Logo = req.Logo
	}

	row, err := s.DB.UpdateBrand(brand)
	if err != nil {
		zap.L().Error("update a brand failed", zap.Error(err))
		return nil, status.Error(codes.Internal, "")
	}
	if row == 0 {
		return nil, status.Error(codes.Unknown, "")
	}

	return &emptypb.Empty{}, nil
}
